/**
 * Copyright (c) iwindplus Technologies Co., Ltd.2024-2030, All rights reserved.
 */

package com.iwindplus.gateway.server.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.iwindplus.boot.domain.constant.CommonConstant;
import com.iwindplus.boot.domain.constant.CommonConstant.HeaderConstant;
import com.iwindplus.boot.domain.constant.CommonConstant.TraceConstant;
import com.iwindplus.boot.util.HttpsUtil;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.support.ipresolver.XForwardedRemoteAddressResolver;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;

/**
 * OAuth2 Endpoint 工具类
 *
 * @author zengdegui
 * @since 2024/05/22 22:22
 */
@Slf4j
public class GatewayUtil {

    private GatewayUtil() {
        throw new IllegalStateException(CommonConstant.UTILITY_CLASS);
    }

    /**
     * 获取请求头所有数据.
     *
     * @param exchange 请求
     * @return Map<String, String>
     */
    public static Map<String, String> getHeaders(ServerWebExchange exchange) {
        final ServerHttpRequest request = exchange.getRequest();
        Map<String, String> headersMap = HttpsUtil.getHeaders(request);
        if (log.isInfoEnabled()) {
            HttpsUtil.getHeadersSize(headersMap);
        }
        return headersMap;
    }

    /**
     * 从请求中，获得认证 Token
     *
     * @param exchange 请求
     * @return String
     */
    public static String getAuthorization(ServerWebExchange exchange) {
        final Map<String, String> headers = GatewayUtil.getHeaders(exchange);
        final String authorizationParam = headers.get(HttpHeaders.AUTHORIZATION);
        final String wsAuthorizationParam = headers.get(HeaderConstant.SEC_WEBSOCKET_PROTOCOL);
        final String token = Optional.ofNullable(authorizationParam).orElse(wsAuthorizationParam);
        if (CharSequenceUtil.isNotBlank(token)) {
            return CharSequenceUtil.replace(token, HeaderConstant.BEARER_TYPE, "").trim();
        }
        return null;
    }

    /**
     * 往请求头设置数据.
     *
     * @param builder builder
     * @param obj     对象
     * @return Map<String, String>
     */
    public static Map<String, String> buildInHeader(ServerHttpRequest.Builder builder, Object obj) {
        Map<String, String> map = BeanUtil.beanToMap(obj)
            .entrySet().stream().filter(m -> Objects.nonNull(m.getValue()))
            .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().toString()));
        for (Map.Entry<String, String> entry : map.entrySet()) {
            builder.header(entry.getKey(), entry.getValue());
        }
        return map;
    }

    /**
     * 移除防伪造请求头.
     *
     * @param exchange 请求
     */
    public static void removeUserHeader(ServerWebExchange exchange) {
        ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
        builder.headers(k -> {
            if (CharSequenceUtil.isNotBlank(k.getFirst(HeaderConstant.USER_INFO))) {
                k.remove(HeaderConstant.USER_INFO);
            }
            if (CharSequenceUtil.isNotBlank(k.getFirst(HeaderConstant.X_FORWARDED_FOR))) {
                k.remove(HeaderConstant.X_FORWARDED_FOR);
            }
            if (CharSequenceUtil.isNotBlank(k.getFirst(TraceConstant.TRACE_ID))) {
                k.remove(TraceConstant.TRACE_ID);
            }
            if (CharSequenceUtil.isNotBlank(k.getFirst(TraceConstant.SPAN_ID))) {
                k.remove(TraceConstant.SPAN_ID);
            }
            if (CharSequenceUtil.isNotBlank(k.getFirst(TraceConstant.REAL_IP))) {
                k.remove(TraceConstant.REAL_IP);
            }
        });
    }

    /**
     * 移除Authorization请求头.
     *
     * @param exchange 请求
     */
    public static void removeAuthorizationHeader(ServerWebExchange exchange) {
        ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
        builder.headers(k -> {
            if (CharSequenceUtil.isNotBlank(k.getFirst(HttpHeaders.AUTHORIZATION))) {
                k.remove(HttpHeaders.AUTHORIZATION);
            }
            if (CharSequenceUtil.isNotBlank(k.getFirst(CommonConstant.HeaderConstant.SEC_WEBSOCKET_PROTOCOL))) {
                k.remove(CommonConstant.HeaderConstant.SEC_WEBSOCKET_PROTOCOL);
            }
        });
    }

    /**
     * 获取真实ip.
     *
     * @param exchange 请求
     * @return String
     */
    public static String getRealIp(ServerWebExchange exchange) {
        XForwardedRemoteAddressResolver xForwardedRemoteAddressResolver = XForwardedRemoteAddressResolver.maxTrustedIndex(1);
        InetSocketAddress inetSocketAddress = xForwardedRemoteAddressResolver.resolve(exchange);
        return Optional.ofNullable(inetSocketAddress).map(InetSocketAddress::getAddress).map(InetAddress::getHostAddress).orElse(null);
    }
}
